package com.scvtc.utils;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.ExpiredJwtException;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * @Description:
 * @author: yiFei
 * @date: 2022/1/3 23:04
 */
@Component
public class JwtUtil {

    private JwtUtil() {
    }

    @Value("${jwt.secret-key}")
    private String secretKey;

    @Value("${jwt.expiration-day}")
    private Integer expirationDay;

    @Autowired
    private ObjectMapper objectMapper;

    /**
     * 创建一个Jwt
     *
     * @param key
     * @param info
     * @return
     */
    public String creatJwtToken(String key, Object info) {
        return Jwts.builder()
                .signWith(SignatureAlgorithm.HS256, secretKey)
                .setSubject("yiFei")
                .setClaims(conversionInfoToJson(key, info))
                .setExpiration(getExpirationTime())
                .compact();
    }

    /**
     * 可以指定过期时间 项目用到再改 访问控制
     *
     * @param key
     * @param info
     * @param expirationDate
     * @return
     */
    private String creatJwtToken(String key, Object info, Date expirationDate) {
        return Jwts.builder()
                .signWith(SignatureAlgorithm.HS256, secretKey)
                .setSubject("yiFei")
                .setClaims(conversionInfoToJson(key, info))
                .setExpiration(expirationDate)
                .compact();
    }

    /**
     * 根据key拿到对应的值
     *
     * @param key
     * @param token
     * @param valueType
     * @param <T>
     * @return
     */
    public <T> T getTokenInfo(String key, String token, Class<T> valueType) {
        return conversionJsonToObject(key, token, valueType);
    }

    public Boolean refreshToken(String token) {
        if (!isExpiration(token)) {
            getClaim(token).setExpiration(getExpirationTime());
            return true;
        } else {
            return false;
        }

    }

    /**
     * 判断是否过期
     *
     * @param token
     * @return
     */
    public Boolean isExpiration(String token) {
        Claims claim = getClaim(token);
        if (claim == null) return true;
        return claim.getExpiration().before(new Date());
    }

    /**
     * 拿取Claims
     *
     * @param token
     * @return
     */
    private Claims getClaim(String token) {
        try {
            return Jwts.parser()
                    .setSigningKey(secretKey)
                    .parseClaimsJws(token)
                    .getBody();
        } catch (ExpiredJwtException e) {
            return null;
        }
    }


    /**
     * 转换为过期时间 以小时为单位
     *
     * @return
     */
    private Date getExpirationTime() {
        Calendar instance = Calendar.getInstance();
        instance.add(Calendar.DATE, expirationDay);
        return instance.getTime();
    }

    /**
     * 将 对象转换为json
     *
     * @param info
     * @return
     */
    private Map<String, Object> conversionInfoToJson(String key, Object info) {
        Map<String, Object> stringObjectMap = new HashMap<>();
        try {
            info = objectMapper.writeValueAsString(info);
            stringObjectMap.put(key, info);
            return stringObjectMap;
        } catch (JsonProcessingException e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 将String转换为对象
     */
    private <T> T conversionJsonToObject(String key, String token, Class<T> valueType) {
        try {
            return objectMapper.readValue((String) getClaim(token).get(key), valueType);
        } catch (JsonProcessingException e) {
            e.printStackTrace();
            return null;
        }

    }

}
